home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-05 / drivers1.zip / 3C505.ASM < prev    next >
Assembly Source File  |  1992-01-23  |  20KB  |  890 lines

  1. version    equ    1
  2.  
  3.     include    defs.asm    ;SEE ENCLOSED COPYRIGHT MESSAGE
  4.  
  5. ; PC/FTP Packet Driver Source, conforming to version 1.08 of spec
  6. ; Krishnan Gopalan and Gregg Stefancik, Clemson Univesity Engineering
  7. ; Computer Operations.
  8. ; Date: September 1, 1989
  9. ; Portions of the code have been adapted from the 3c505 driver for NCSA
  10. ; Telnet by Bruce Orchard and later modified by Warren Van Houten and krus
  11. ; @diku.dk.
  12.  
  13. ; Permission is granted to any individual or institution to use,copy,
  14. ; modify or redistribute this software provided this notice is retained.
  15. ; The authors make no guarantee to the suitability of the software for
  16. ; any purpose. Any damage caused by using this program is the responsibility
  17. ; of the user and not the authors. 
  18.  
  19. code    segment    word public
  20.     assume    cs:code, ds:code
  21.  
  22. ;    3c505 card definitions
  23. ;control register    bit definitions
  24. EN_ATTN            equ    0200q
  25. EN_FLSH_DATA        equ    0100q
  26. EN_DMA_ENABLE        equ    0040q
  27. EN_TO_HOST        equ    0020q
  28. EN_TERMINAL_CNT_ENBLE     equ    0010q
  29. EN_COMMAND_ENABLE    equ    0004q
  30. EN_HSF2            equ    0002q
  31. EN_HSF1            equ    0001q
  32.  
  33. ;status register    bit definitions
  34.  
  35. EN_DATA_READY        equ    0200q
  36. EN_HOST_COMMAND_EMPTY    equ    0100q
  37. EN_ADAPTER_COMMAND_FULL equ    0040q
  38. EN_TO_HOST        equ    0020q
  39. EN_DMA_DONE        equ    0010q
  40. EN_ASF3            equ    0004q
  41. EN_ASF2            equ    0002q
  42. EN_ASF1            equ    0001q
  43. ; auxiliary dma register  bit definition
  44. EN_BURST        equ    0001q
  45.  
  46. ; timeout values
  47. SECOND        EQU    36
  48. RESDEL        EQU    6
  49. RESTO        EQU    15*SECOND
  50. CMDBTO        EQU    6
  51. CMDCTO        EQU    6
  52. RETRYDELAY      EQU    6
  53. RCMDTO        EQU    6
  54. RESPTO        EQU    6
  55.  
  56. ;port addresses
  57. ECOMMAND    equ    0
  58. ESTATUS     equ    2
  59. EDATA         equ    4
  60. ECONTROL     equ    6
  61.  
  62. recvbuf        db  4096 dup(?)        ; size of receive buffer
  63. rbufct        dw    ?        ; recv buffer count
  64.  
  65. pcblen        dw     ?        ; length of pcb
  66. pcbaddr        dw    ?        ; address of pcb
  67.  
  68. lastcon        db    ?        ; last control to board
  69. cmdlen        dw    ?        ; length of command
  70.  
  71. cbsh        equ    50
  72. cbs        equ    cbsh*2    
  73.  
  74. icmdb        db    cbs dup(?)
  75. icmd        db    cbsh dup(?)
  76.  
  77. fconc        db    0    ; flag configure 82586
  78. fgeth        db    0    ; flag:get ethernet address
  79. fseth        db    0    ; flag:set ethernet address
  80. fxmit        db    0    ; flag:transmit packet
  81.  
  82. cconc        db    02h    ; command configure 82586
  83.         db    2    ; 2 more bytes
  84.         dw    1    ; receive broadcasts
  85.  
  86. rconc        db    2 dup(?);Response; configure
  87. rconc_st    dw    ?    ; status
  88.  
  89. cgeth        db    03h    ; command get ethernet address
  90.         db    00    ; no more bytes
  91.  
  92. txmit        db    09h    ; command ; transmit packet
  93.         db    06    ; 6 more bytes
  94. tx_offset    dw    ?    ; offset of host transmit buffer 
  95. tx_segment    dw    ?    ; segment of host transmit buffer 
  96. tx_length    dw    ?    ; packet length
  97.  
  98. rxmit        db    2 dup(?); Response tx packet
  99. rx_offset    dw    ?    ; buffer offset
  100. rx_segment    dw    ?    ; buffer segment
  101. rx_status    dw    ?    ; completion status
  102. rx_cstatus    dw    ?    ; 82586 status
  103.  
  104. rgeth        db    2 dup(?); Response get Ethernet address
  105. rgeth_ad    db    6 dup(?); -- address
  106.  
  107. cseth        db    10h    ; command :set station address
  108.         db    6    ; 6 more bytes
  109. cseth_ad    db    6 dup(?); ethernet address
  110.  
  111. rseth        db    2 dup(?); response set ethernet address
  112. rseth_status    dw    ?    ; status
  113.  
  114. crecv        db    08h    ; command receive
  115.         db    08    ; 8 more bytes
  116. crecv_offset    dw    ?    ; buffer offset
  117. crecv_segment    dw    ?    ; buffer segment
  118. crecv_length    dw    ?    ; buffer length
  119. crecv_timeout    dw    ?    ; timeout
  120.  
  121. rr        db    2 dup(?); Response; receive
  122. rr_offset    dw    ?    ; buffer offset
  123. rr_segment    dw    ?    ; buffer segment
  124. rr_dmalen    dw    ?    ; buffer dmalen
  125. rr_length    dw    ?    ; packet length
  126. rr_status    dw    ?    ; completion status
  127. rr_rstatus    dw    ?    ; 82586 receive status
  128. rr_time        dd    ?    ; time tag
  129.         
  130. public    int_no,io_addr,mem_base
  131.  
  132. int_no     db    2,0,0,0            ;must be four bytes long for get_number.
  133. io_addr dw    0300h,0            ; io addr for card(jumpers)
  134. mem_base dw    0d000h,0        ; shared memory address(software)
  135.  
  136. public    driver_class, driver_type, driver_name, driver_function, parameter_list
  137.  
  138. driver_class    db    BLUEBOOK, IEEE8023, 0        ;from the packet spec 
  139. driver_type    db    2        ;from the packet spec 
  140. driver_name    db    '3C505',0    ;name of the driver.  
  141. driver_function    db    2
  142. parameter_list    label    byte
  143.     db    1    ;major rev of packet driver
  144.     db    9    ;minor rev of packet driver
  145.     db    14    ;length of parameter list
  146.     db    EADDR_LEN    ;length of MAC-layer address
  147.     dw    GIANT    ;MTU, including MAC headers
  148.     dw    MAX_MULTICAST * EADDR_LEN    ;buffer size of multicast addrs
  149.     dw    0    ;(# of back-to-back MTU rcvs) - 1
  150.     dw    0    ;(# of successive xmits) - 1
  151. int_num    dw    0    ;Interrupt # to hook for post-EOI
  152.             ;processing, 0 == none,
  153.  
  154.     public    rcv_modes
  155. rcv_modes    dw    4        ;number of receive modes in our table.
  156.         dw    0,0,0,rcv_mode_3
  157.  
  158.     public    as_send_pkt
  159. ; The Asynchronous Transmit Packet routine.
  160. ; Enter with es:di -> i/o control block, ds:si -> packet, cx = packet length,
  161. ;   interrupts possibly enabled.
  162. ; Exit with nc if ok, or else cy if error, dh set to error number.
  163. ;   es:di and interrupt enable flag preserved on exit.
  164. as_send_pkt:
  165.     ret
  166.  
  167.     public    drop_pkt
  168. ; Drop a packet from the queue.
  169. ; Enter with es:di -> iocb.
  170. drop_pkt:
  171.     assume    ds:nothing
  172.     ret
  173.  
  174.     public    xmit
  175. ; Process a transmit interrupt with the least possible latency to achieve
  176. ;   back-to-back packet transmissions.
  177. ; May only use ax and dx.
  178. xmit:
  179.     assume    ds:nothing
  180.     ret
  181.  
  182.  
  183.     public    send_pkt
  184. send_pkt:
  185. ;enter with es:di->upcall routine, (0:0) if no upcall is desired.
  186. ;  (only if the high-performance bit is set in driver_function)
  187. ;enter with ds:si -> packet, cx = packet length.
  188. ;exit with nc if ok, or else cy if error, dh set to error number.
  189.     assume    ds:nothing
  190.  
  191.     push    si            ; save si for  lodsw
  192.     push    ds            ; save ds
  193.     push    es            ; save es for timer
  194.     push    cs            ;
  195.     pop    ds            ; cs = ds align
  196.  
  197.     mov    tx_segment,ds        ;tx->data
  198.     mov    tx_offset,si        ;tx_offset ->segment offset 
  199.  
  200.     mov    ax,cx            ; save cx
  201.     cmp    ax,60            ; compare with minimum limit
  202.     jnb    pkt_ok            ; go if ok 
  203.     mov    ax,60            ; make length minimum allowed
  204. pkt_ok:
  205.     inc    ax            ; round up
  206.     sar    ax,1            ; divide by 2
  207.     shl    ax,1            ; multiply by 2
  208.     mov    tx_length,ax        ; put in request
  209.     
  210.     mov    fxmit,0            ; clear response received flag
  211.  
  212.     mov    si, offset txmit    ; si->request(pcb)
  213.     mov    ax,8            ;length of pcb 
  214.  
  215.     call    outpcb            ; send command to board
  216.  
  217.     mov    cx,tx_length
  218.     sar    cx,1
  219.  
  220.     pop    es
  221.     pop    ds
  222.     pop    si
  223.  
  224. tx_1:
  225.  
  226.     lodsw
  227.  
  228.     loadport
  229.     setport    EDATA
  230.     out    dx,ax            ; output word
  231.     setport    ESTATUS
  232. tx_2:
  233.     in    al,dx            ; get status
  234.     test    al, EN_DATA_READY    ; ready for next word ?
  235.     jz    tx_2            ;no
  236.  
  237.     dec    cx            ; count word
  238.     jnz    tx_1            ; loop thru buffer
  239.  
  240. tx_3:
  241.     test    fxmit,0ffh        ; is transmit over
  242.     jz    tx_3            ; no
  243.     ret
  244.  
  245.     public    get_address
  246.  
  247.  
  248. get_address:
  249. ;get the address of the interface.
  250. ;enter with es:di -> place to get the address, cx = size of address buffer.
  251. ;exit with nc, cx = actual size of address, or cy if buffer not big enough.
  252.     assume    ds:code
  253.     push    es
  254.     push    di
  255.  
  256.     cmp    cx, EADDR_LEN        ; does caller want reasonable length?
  257.     jb    get_addr_fail        ; no , fails
  258.     mov    si,offset cgeth        ; si->pcb address
  259.     mov    ax,2            ; length of pcb
  260.     mov    fgeth,0            ; clear response received flag
  261.  
  262.     call    outpcb        
  263.  
  264.     mov    ax,RESTO        ; get wait time
  265.     call    set_timeout
  266. get_addr_1:
  267.     test    fgeth,0ffh        ; answered?
  268.     jnz    get_addr_2        ; yes
  269.     call    do_timeout
  270.     jnz    get_addr_1        ; test again
  271.     jmp    get_addr_fail        ; go return
  272.  
  273. get_addr_2:
  274.     pop    di
  275.     pop    es
  276.     cld                ; make sure of string operation
  277.     mov    si,offset rgeth_ad    ; load source of address
  278.     mov    cx,EADDR_LEN        ; return length of address
  279.     rep    movsb            ; copy address
  280.     mov    cx,EADDR_LEN        ; return length of address
  281.     clc
  282.     ret
  283. get_addr_fail:
  284.     add sp,4
  285.     stc
  286.     ret
  287.  
  288.     public    set_address
  289.  
  290. set_address:
  291. ;enter with ds:si -> Ethernet address, CX = length of address.
  292. ;exit with nc if okay, or cy, dh=error if any errors.
  293.     assume    ds:nothing
  294.  
  295.     cmp    cx, EADDR_LEN        ; check if address ok
  296.     je    set_addr_1    
  297.     mov    dh,BAD_ADDRESS        ; don't like length
  298.     stc
  299.     ret
  300. set_addr_1:
  301.     mov    di,offset cseth_ad    ;di->destination offset
  302.     rep    movsb            ; return address
  303.     mov    si,offset cseth        ; si->request ethernet address
  304.     mov    ax,8            ; request length -> ax
  305.     mov    fseth,0            ; clear response received flag
  306.     call     outpcb            ; send the pcb
  307.  
  308.     mov    ax,RESTO        ; get response time
  309.     call    set_timeout
  310. set_addr_2:
  311.     test    fseth,0ffh        ; pcb answered?
  312.     jnz    set_addr_3
  313.     call    do_timeout        ; has time expired
  314.     jne    set_addr_2        ; no, go back
  315.     stc                ; error
  316.     ret
  317. set_addr_3:
  318.     mov    cx,EADDR_LEN        ;return their address length.
  319.     clc
  320.     ret
  321.  
  322. rcv_mode_3:
  323. ;receive mode 3 is the only one we support, so we don't have to do anything.
  324.     ret
  325.  
  326.  
  327.     public    set_multicast_list
  328. set_multicast_list:
  329. ;enter with ds:si ->list of multicast addresses, cx = number of addresses.
  330. ;return nc if we set all of them, or cy,dh=error if we didn't.
  331.     mov    dh,NO_MULTICAST
  332.     stc
  333.     ret
  334.  
  335.  
  336.     public    terminate
  337. terminate:
  338.     ret
  339.  
  340.     public    reset_interface
  341. reset_interface:
  342. ;reset the interface.
  343.     assume    ds:code
  344.  
  345.     mov    al, EN_ATTN OR EN_FLSH_DATA    ; hard reset command
  346.     loadport
  347.     setport    ECONTROL
  348.     out    dx,al                ; do reset
  349.     mov    ax,RESDEL            ; get reset delay
  350.     call    set_timeout
  351. rst1:
  352.     call    do_timeout
  353.     jne    rst1                ; wait for reset
  354.     mov    al,EN_COMMAND_ENABLE        ; command interrupt enable
  355.     mov    lastcon,al            ; save last command
  356.     out    dx,al                ; release reset
  357.     mov    ax,RESDEL
  358.     call    set_timeout
  359. rst2:
  360.     call    do_timeout
  361.     jne    rst2                ; wait to start reset
  362.     mov    ax,RESTO            ; add time out
  363.     call    set_timeout
  364. rst3:
  365.     call getstat                ; getstatus    
  366.     and    ax,EN_ASF1 OR EN_ASF2        ; 
  367.     cmp    ax,EN_ASF1 OR EN_ASF2        ;  both on ?
  368.     jne     resdone
  369.     call    do_timeout            ; long enough?
  370.     jne    rst3                ; no
  371.     ret
  372. resdone:
  373.     ret
  374. ;called when we want to determine what to do with a received packet.
  375. ;enter with cx = packet length, es:di -> packet type, dl = packet class.
  376.     extrn    recv_find: near
  377.  
  378. ;called after we have copied the packet into the buffer.
  379. ;enter with ds:si ->the packet, cx = length of the packet.
  380.     extrn    recv_copy: near
  381.  
  382.     extrn    count_in_err: near
  383.     extrn    count_out_err: near
  384.  
  385.     public    recv
  386. recv:
  387. ;called from the recv isr.  All registers have been saved, and ds=cs.
  388. ; all interrupts come here
  389. ;Upon exit, the interrupt will be acknowledged.
  390.     assume    ds:code
  391.     ;sti
  392.     cld
  393. recv1:
  394.     loadport
  395.     setport    ESTATUS
  396.     in    al,dx                ; read flags
  397.     and    al,EN_ADAPTER_COMMAND_FULL    ; 
  398.     jnz    recv2                ; yes,full
  399.     jmp    interrupt_done    
  400. ;there might be a response, clear flags to check for response
  401. recv2:
  402.     mov    ax,RCMDTO            ; incoming command time out
  403.     call    set_timeout
  404.  
  405.     mov    al,lastcon            ; last control->ax
  406.     and    al,NOT (EN_HSF1 OR EN_HSF2)    ; clear flags
  407.     mov    lastcon,al
  408.  
  409.     loadport
  410.     setport    ECONTROL
  411.     out    dx,al                ; clear flags in cntl reg
  412.  
  413.     mov    di,offset icmdb            ; di->incoming command buffer
  414.  
  415. recv3:
  416.     loadport
  417.     setport    ESTATUS
  418.     in    al,dx                ; status->al
  419.  
  420.     mov    cx,ax                ; status->cx
  421.     test    al,EN_ADAPTER_COMMAND_FULL    ; is adapter register full
  422.     jnz    recv4                ; yes go ahead to read from
  423.     call    do_timeout            ; is time up ? 
  424.     jne    recv3                ; give some more time
  425.     jmp    int1                ; give up
  426. recv4:
  427.     loadport
  428.     setport    ECOMMAND
  429.     in    al,dx                ; get command byte
  430.     and    cl,EN_ASF1 OR EN_ASF2        
  431.     cmp    cl,EN_ASF1 OR EN_ASF2        ; both on?
  432.     je    recv5                ; end of command
  433.     mov    [di],al                ;save byte
  434.     inc    di                ;inc    di 
  435.     mov    ax,di                ; current pointer->ax
  436.     sub    ax,offset icmdb            ; - start of buffer
  437.     cmp    ax,cbs                ; full?
  438.     jl    recv3
  439.  
  440.     mov    si,(offset icmdb)+cbsh        ; si->middle of buffer
  441.     mov    di,offset icmdb            ; di->start of buffer
  442.     mov    cx,cbsh                ; size of half buffer->cx
  443.     push    ds
  444.     pop    es
  445.     rep    movsb
  446.  
  447.     jmp    recv3                ; loop for more bytes
  448. recv5:
  449.     push    ds
  450.     pop    es
  451.     mov    ah,0
  452.     mov    cmdlen,ax            ; save cmdlen
  453.     mov    si,di 
  454.     sub    si,cmdlen
  455.     mov    di,offset icmd    
  456.     mov    cx,cmdlen
  457.  
  458.     rep movsb                ; copy
  459.  
  460.     mov    al,icmd                ; check
  461.  
  462.     cmp    al,32h                ; Configure?
  463.     je    respconfig
  464.  
  465.     cmp    al,33h                ; get ethernet address?
  466.     je    respgetaddr            ; yes
  467.  
  468.     cmp    al,39h                ; transmit complete?
  469.     je    transmit            ; yes
  470.  
  471.     cmp    al,40h                ; set ethernet address
  472.     je    respsetaddr            ; yes
  473.     
  474.     cmp    al,38h                ; receive complete?
  475.     je    resprecv
  476.  
  477.     jmp    int1
  478.  
  479. respconfig:
  480.  
  481.     push    ds
  482.     pop    es
  483.     mov    si,offset icmd
  484.     mov    di,offset rconc
  485.     mov    cx,2
  486.     
  487.     rep    movsw
  488.     mov    fconc,1
  489.     jmp    int1
  490.     
  491. respgetaddr:
  492.     push    ds
  493.     pop    es
  494.  
  495.     mov    si,offset icmd
  496.     mov    di,offset rgeth
  497.     mov    cx,4
  498.  
  499.     rep    movsw
  500.  
  501.     mov    fgeth,1
  502.     jmp    int1
  503.  
  504. respsetaddr:
  505.  
  506.     mov    si,offset icmd        ; si->command received
  507.     mov    di,offset cseth        ; di->set ethernet address resp
  508.     push    ds
  509.     pop    es
  510.     mov    cx,2
  511.  
  512.     rep    movsw
  513.     mov    fseth,1
  514.     jmp    int1
  515.  
  516. transmit:
  517.     mov    si,offset icmd            ; si->command received
  518.     mov    di,offset rxmit            ; response,transmit packet
  519.     push    ds
  520.     pop    es
  521.     mov    cx,5                ; response length->cx
  522.     rep    movsw
  523.  
  524.     mov    fxmit,1                ; response received
  525.     jmp    int1                ; return from interrupt
  526.  
  527. resprecv:
  528.     mov    si,offset icmd            ; si->command received
  529.     mov    di,offset rr            ; di->receive response
  530.     push    ds
  531.     pop    es
  532.     mov    cx,9                ; response length->cx
  533.     
  534.     rep    movsw                ; move response
  535.     mov    di,offset recvbuf        ; di->receive buffer
  536.     mov    ax,rr_length            ; message size->ax
  537.     inc    ax                ; round up
  538.     shr    ax,1                ; convert to words
  539.     shl    ax,1                ; convert to characters
  540.     mov    rr_length,ax            ; ax->message length
  541.  
  542.     mov    cx,ax                ; message length->cx
  543.     shr    cx,1                ; convert to words
  544.  
  545.     mov    al,lastcon            ; lastcontrol->al
  546.     or    al,EN_TO_HOST OR EN_HSF1    ; set direction & ack    
  547.     mov    lastcon,al            ; response
  548.  
  549.     loadport
  550.     setport    ECONTROL
  551.     out    dx,al                ; pass direction
  552.     
  553.     setport ESTATUS
  554.  
  555. resprecv_1:
  556.  
  557.     in    al,dx                ; get status
  558.     test    al,EN_DATA_READY        ; data ready ?
  559.     jz    resprecv_1
  560.  
  561.     setport    EDATA                ; data word->ax
  562.     in    ax,dx                ; get word
  563.     stosw                    ; store word in buffer
  564.  
  565.     setport    ESTATUS
  566.     dec    cx                ; count word
  567.     jnz    resprecv_1            ; loop if more words
  568.  
  569.     mov    al,lastcon
  570.     and    al,NOT (EN_TO_HOST OR EN_HSF1)
  571.     mov    lastcon,al
  572.  
  573.     loadport                ; dx->control register
  574.     setport    ECONTROL
  575.     out    dx,al
  576.  
  577.     mov    cx,rr_length            ; cx->packet length
  578.  
  579.     push    cs                ; align cs and ds
  580.     pop    ds
  581.  
  582.     mov    di,offset recvbuf        ; reset di to beginning
  583.     add    di,EADDR_LEN+EADDR_LEN        ; point to type field
  584.                         ; of buffer
  585.     assume    ds:code
  586.  
  587.     mov    dl, BLUEBOOK        ;assume bluebook Ethernet.
  588.     mov    ax, es:[di]
  589.     xchg    ah, al
  590.     cmp     ax, 1500
  591.     ja    BlueBookPacket
  592.     inc    di            ;set di to 802.2 header
  593.     inc    di
  594.     mov    dl, IEEE8023
  595. BlueBookPacket:
  596.  
  597.     call    recv_find            ; first call
  598.  
  599.     assume    ds:nothing
  600.     mov    ax,es                ; ax->es
  601.     or    ax,di                ; is es=di=0?
  602.     je    rcv_no_copy
  603.  
  604.     mov    cx,rr_length            ; cx->packet length
  605.     push    cx
  606.     push    es
  607.     push    di
  608.  
  609.     mov    si,offset recvbuf        ; prepare to copy the packet
  610.     rep    movsb                ; copy
  611.  
  612.     pop    si
  613.     pop    ds
  614.     pop    cx
  615.  
  616.     call    recv_copy            ; second call 
  617. rcv_no_copy:
  618.     push    cs
  619.     pop    ds
  620.     call    anotherrecv            ; start another recv
  621. int1:
  622.     jmp    recv1
  623.  
  624. interrupt_done:
  625.     ret
  626.  
  627. ;*****************************OUTPCB***********************************
  628. ;outpcb     send pcb to board, retry until accepted
  629. ; entry    ax = number of bytes in pcb
  630. ;    si = address of pcb
  631. outpcb    proc     near
  632.     mov    pcblen,ax        ; save pcb length
  633.     mov    pcbaddr,si        ; save pcb address
  634. pcb_0:
  635.     mov    cx,pcblen        ;length->cx
  636.     mov    si,pcbaddr        ; address->si
  637.     cli                ; stop interrupts
  638.     mov    al,lastcon        ; save last command
  639.     and    al, NOT (EN_HSF1 OR EN_HSF2); clear flags
  640.     mov    lastcon,al
  641.     sti                ; enable interrupts
  642.     loadport
  643.     setport    ECONTROL
  644.     out    dx,al            ; send control
  645.     setport    ECOMMAND
  646. pcb_1:
  647.     mov    al,[si]            ; 
  648.     out    dx,al            ; send command byte
  649.     mov    ax,CMDBTO        ; get time out
  650.     call    set_timeout
  651. chk_hcre:
  652.     call    getstat
  653.     and    al, EN_HOST_COMMAND_EMPTY    ; command accepted
  654.     jne    pcb_2                ; go on
  655.     call    do_timeout
  656.     jne    chk_hcre            ; time is still left
  657.     jmp    cmdretry            ; retry command
  658. pcb_2:
  659.     inc    si                ; increment source pointer
  660.     dec    cx                ; count byte
  661.     jg    pcb_1                ; loop         
  662.     loadport
  663.     setport    ECONTROL
  664.     cli                    ; disable interrupts
  665.     mov    al,lastcon            ; last control -> al
  666.     or    al,(EN_HSF1 OR EN_HSF2)        ; set end of command
  667.     mov    lastcon,al            ; save last control
  668.     out    dx,al                ; send flag bits
  669.     setport    ECOMMAND
  670.     mov    ax,pcblen
  671.     out    dx,al                ; send pcb length
  672.     sti                    ; enable interrupts
  673.     mov    ax,CMDCTO            ; time out for acceptance
  674.     call    set_timeout
  675. pcb_3:
  676.     call    getstat
  677.     and    al,(EN_ASF1 OR EN_ASF2)        ; just keep status flags
  678.     cmp    al,1                ; accepted
  679.     je    cmdaccept
  680.     cmp    al,2
  681.     je    cmdretry
  682.     call    do_timeout
  683.     jne    pcb_3
  684.  
  685. cmdretry:
  686.     mov    ax,RETRYDELAY            ;add retry delay
  687.     call    set_timeout
  688. pcb_4:
  689.     call    do_timeout
  690.     jne    pcb_4
  691.     jmp    pcb_0
  692.  
  693. cmdaccept:
  694.     cli
  695.     mov    al,lastcon
  696.     and    al, NOT (EN_HSF1 OR EN_HSF2)    ; turn off end of command flag
  697.     mov    lastcon,al            ; save last control
  698.     sti                    ; enable interrupts
  699.     loadport
  700.     setport    ECONTROL
  701.     out    dx,al                ; pass control byte
  702.     ret    
  703. outpcb    endp
  704. ;*************get status of board***********************
  705. getstat        proc    near
  706.     push    bx
  707.     push    dx
  708.     loadport
  709.     setport    ESTATUS
  710.  
  711. stat_1:
  712.     in    al,dx            ; get status into al
  713.     mov    bl,al            ; save al
  714.     in    al,dx            ; get status again
  715.     cmp    al,bl            ; same status ?
  716.     jne    stat_1
  717.     pop    dx
  718.     pop    bx
  719.     ret
  720. getstat    endp
  721.  
  722. ; UPDATE BUFFER POINTERS AND ISSUE ANOTHER RECV
  723. ;    update recv 
  724. anotherrecv    proc    near
  725.     mov    ax,rbufct
  726.     mov    crecv_offset,ax
  727.     inc    ax
  728.     mov    rbufct,ax
  729.     mov    ax,10
  730.     mov    si,offset crecv
  731.  
  732.     call    outpcb
  733.     ret
  734. anotherrecv    endp
  735.  
  736.     public    recv_exiting
  737. recv_exiting:
  738. ;called from the recv isr after interrupts have been acknowledged.
  739. ;Only ds and ax have been saved.
  740.     assume    ds:nothing
  741.     ret
  742.  
  743.     include    timeout.asm
  744.  
  745. ;any code after this will not be kept after initialization.
  746. end_resident    label    byte
  747.  
  748.     public    usage_msg
  749. usage_msg  db  "usage: 3C505 [-n] [-d] [-w] <packet_int_no> <int_level> <io_addr> <mem_base>",CR,LF,'$'
  750.     public    copyright_msg
  751. copyright_msg    db    "Packet Driver for 3c505, version ",'0'+(majver / 10),'0'+(majver mod 10), ".",CR,LF
  752.          db    "Portions copyright 1989, Krishnan Gopalan & Gregg Stefancik.",CR,LF
  753.          db     "Clemson University Engineering Comp Ops.",CR,LF,'$'
  754. no_board_msg:
  755.     db    "3c505 apparently not present at this address.",CR,LF,'$'
  756. int_no_name    db    "Interrupt number ",'$'
  757. io_addr_name    db    "I/O port ",'$'
  758. mem_base_name    db    "Memory address ",'$'
  759.  
  760.     extrn    set_recv_isr: near
  761.  
  762. ;enter with si -> argument string, di -> word to store.
  763. ;if there is no number, don't change the number.
  764.     extrn    get_number: near
  765.  
  766. ;enter with dx -> name of word, di -> dword to print.
  767.     extrn    print_number: near
  768.  
  769.     public    parse_args
  770. parse_args:
  771. ;exit with nc if all went well, cy otherwise.
  772.     mov    di,offset int_no
  773.     call     get_number
  774.     mov    di,offset io_addr
  775.     call    get_number
  776.     mov    di,offset mem_base
  777.     call    get_number
  778.     clc
  779.     ret
  780.  
  781.     public    etopen
  782. etopen:
  783. ;if all is okay,
  784. ; reset the 3c505 board takes about 15-20 seconds
  785.     loadport
  786.     setport    ECONTROL 
  787.     mov    al,EN_ATTN OR EN_FLSH_DATA    ; reset command
  788.     out    dx,al                ; do reset
  789.   if 0
  790.     mov    ax,1
  791.     call    set_timeout
  792. reset1:
  793.     call    do_timeout
  794.     jne    reset1                ; wait for reset to propagate
  795.   else
  796.   endif
  797.  
  798.     mov    al,EN_COMMAND_ENABLE        ; command interrupt enable
  799.     mov    lastcon,al            ; save last command
  800.     out    dx,al                ; release reset
  801.     mov    ax,RESDEL            ; time to wait
  802.     call    set_timeout
  803. reset2:
  804.     call    do_timeout
  805.     jne    reset2
  806.  
  807.     mov    ax,RESTO            ;this is the long wait.
  808.     call    set_timeout
  809. reset3:
  810.     call    getstat
  811.     and    ax, EN_HSF1 OR EN_HSF2
  812.     cmp    ax,EN_HSF1 OR    EN_HSF2
  813.     jne    resetdone
  814.     call    do_timeout
  815.     jne    reset3
  816.     jmp    openfail            ; open failed
  817.  
  818. resetdone:
  819.     call    set_recv_isr            ;install the interrupt handler
  820.  
  821. ;Tell the 3c505 board to receive packets
  822.     mov    si,offset cconc
  823.     mov    ax,4
  824.     mov    fconc,0
  825.  
  826.     call    outpcb
  827.  
  828.     mov    ax,RESTO
  829.     call    set_timeout
  830. open_1:
  831.     test    fconc,0ffh
  832.     jnz    setuprecv
  833.  
  834.     call    do_timeout
  835.     jne    open_1
  836.  
  837. ; set up the recv buffers
  838.  
  839. setuprecv:
  840.     mov    rbufct,0            ; clear buffer counter
  841.     mov    crecv_length,1600        ; buffer length,1600
  842.  
  843.     mov    crecv_timeout,0
  844.  
  845. startrecv:
  846.     mov    ax,rbufct            ; buffer counter->ax
  847.     mov    crecv_offset,ax            ; buf no used as offset
  848.     inc    ax                ; count buffer
  849.     mov    rbufct,ax
  850.     mov    ax,10                ; length of pcb
  851.     mov    si,offset crecv            ;si->command receive
  852.  
  853.     call    outpcb                ; pass the pcb
  854.     mov    ax,rbufct
  855.     cmp    ax,10
  856.     jl    startrecv
  857.  
  858.     mov    al, int_no        ; Get board's interrupt vector
  859.     add    al, 8
  860.     cmp    al, 8+8            ; Is it a slave 8259 interrupt?
  861.     jb    set_int_num        ; No.
  862.     add    al, 70h - 8 - 8        ; Map it to the real interrupt.
  863. set_int_num:
  864.     xor    ah, ah            ; Clear high byte
  865.     mov    int_num, ax        ; Set parameter_list int num.
  866.  
  867.     mov    dx,offset end_resident
  868.     clc
  869.     ret
  870.  
  871.     public    print_parameters
  872. print_parameters:
  873.     mov    di,offset int_no
  874.     mov    dx,offset int_no_name
  875.     call     print_number
  876.     mov    di,offset io_addr
  877.     mov    dx,offset io_addr_name
  878.     call    print_number
  879.     mov    di,offset mem_base
  880.     mov    dx,offset mem_base_name
  881.     call    print_number
  882.     ret
  883.  
  884. ;if we got an error,
  885. openfail:
  886.     stc
  887.     ret
  888. code    ends
  889.     end
  890.